package com.ptkc.web;

import com.ptkc.constants.WebResult;
import com.ptkc.utils.*;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.cardinality.Cardinality;
import org.elasticsearch.search.aggregations.metrics.cardinality.CardinalityAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCount;
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCountAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.joda.time.DateTimeZone;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author: Mr.Jiao
 * @date: 2019年01月08日
 */
@RestController
@RequestMapping(value = {"/search/dataCenter"})
public class DataCenterController {

    private final String ORDER_INDEX = "runfast_order";

    private final String ORDER_TYPE = "order";

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @GetMapping(value = "/statistics_by_day")
    public WebResult getOrderInfo(HttpServletRequest request) throws IOException {
        String agents = request.getParameter("agents");
        String starttimeStr = request.getParameter("starttime");
        String endtimeStr = request.getParameter("endtime");
        BoolQueryBuilder parentQueryBuilder = QueryBuilders.boolQuery();
        if(StringUtil.isNotEmpty(agents)){
            parentQueryBuilder.must(QueryBuilders.termsQuery("agentId", agents.split(",")));
        }
        if(NumberUtils.isPositiveInteger(starttimeStr) && NumberUtils.isPositiveInteger(endtimeStr)){
            parentQueryBuilder.must(QueryBuilders.rangeQuery("createTime").from(Long.valueOf(starttimeStr), true).to(Long.valueOf(endtimeStr), true));
        }
        parentQueryBuilder.must(QueryBuilders.termsQuery("status", new Integer[]{-1,8}));

        Map notParams = new HashMap<>();
        DateHistogramAggregationBuilder aggOrderDay = AggregationBuilders.dateHistogram("aggOrderDay").field("createTime").timeZone(DateTimeZone.forID("Asia/Shanghai")).dateHistogramInterval(DateHistogramInterval.DAY).format("yyyy-MM-dd");
        //完成的订单数量
        SumAggregationBuilder aggCompletedCount = AggregationBuilders.sum("aggCompletedCount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_count", notParams));
        //完成的订单金额
        SumAggregationBuilder aggCompletedAmount = AggregationBuilders.sum("aggCompletedAmount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_amount", notParams));
        //完成的配送订单数量
        SumAggregationBuilder aggCompletedByDeliverCount = AggregationBuilders.sum("aggCompletedByDeliverCount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_by_delivery_count", notParams));
        //完成的配送订单金额
        SumAggregationBuilder aggCompletedByDeliverAmount = AggregationBuilders.sum("aggCompletedByDeliverAmount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_by_delivery_amount", notParams));
        //超时完成订单数量
        SumAggregationBuilder aggCompletedOuttimeCount = AggregationBuilders.sum("aggCompletedOuttimeCount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_outtime_count", notParams));
        //超时完成的订单金额
        SumAggregationBuilder aggCompletedOuttimeAmount = AggregationBuilders.sum("aggCompletedOuttimeAmount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_outtime_amount", notParams));
        //取消订单数量
        SumAggregationBuilder aggCancelCount = AggregationBuilders.sum("aggCancelCount").script(new Script(ScriptType.STORED, null, "runfast_order_canceled_count", notParams));
        //取消订单金额
        SumAggregationBuilder aggCancelAmount = AggregationBuilders.sum("aggCancelAmount").script(new Script(ScriptType.STORED, null, "runfast_order_canceled_amount", notParams));
        //差评订单数量
        SumAggregationBuilder aggNegativeCount = AggregationBuilders.sum("aggNegativeCount").script(new Script(ScriptType.STORED, null, "runfast_order_negative_count", notParams));
        //差评订单金额
        SumAggregationBuilder aggNegativeAmount = AggregationBuilders.sum("aggNegativeAmount").script(new Script(ScriptType.STORED, null, "runfast_order_negative_amount", notParams));
        //新用户订单数量
        SumAggregationBuilder aggNewUserOrderCount = AggregationBuilders.sum("aggNewUserOrderCount").script(new Script(ScriptType.STORED, null, "runfast_order_of_firsttime_count", notParams));
        //新用户订单金额
        SumAggregationBuilder aggNewUserOrderAmount = AggregationBuilders.sum("aggNewUserOrderAmount").script(new Script(ScriptType.STORED, null, "runfast_order_of_firsttime_amount", notParams));

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        aggOrderDay.subAggregation(aggCompletedCount).subAggregation(aggCompletedByDeliverCount).subAggregation(aggCompletedByDeliverAmount).subAggregation(aggCompletedOuttimeCount)
                .subAggregation(aggCompletedAmount).subAggregation(aggCompletedOuttimeAmount).subAggregation(aggCancelCount).subAggregation(aggCancelAmount).subAggregation(aggNegativeCount)
                .subAggregation(aggNegativeAmount).subAggregation(aggNewUserOrderCount).subAggregation(aggNewUserOrderAmount);
        sourceBuilder.from(0).size(0).query(parentQueryBuilder).aggregation(aggOrderDay);
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(ORDER_INDEX).types(ORDER_TYPE).source(sourceBuilder);
        System.out.println(searchRequest.source());
        SearchResponse response = this.restHighLevelClient.search(searchRequest);
        if(response.status() == RestStatus.OK){
            Aggregations aggregations = response.getAggregations();
            if(aggregations != null) {
                Histogram orderDay = aggregations.get("aggOrderDay");
                List<? extends Histogram.Bucket> buckets = orderDay.getBuckets();
                List<Object> dayArrays = new ArrayList<>();
                String[] aggKeyItems = {
                        "aggCompletedCount",
                        "aggCompletedAmount",
                        "aggCompletedByDeliverCount",
                        "aggCompletedByDeliverAmount",
                        "aggCompletedOuttimeCount",
                        "aggCompletedOuttimeAmount",
                        "aggCancelCount",
                        "aggCancelAmount",
                        "aggNegativeCount",
                        "aggNegativeAmount",
                        "aggNewUserOrderCount",
                        "aggNewUserOrderAmount"
                };
                for(Histogram.Bucket bucket : buckets){
                    String time = bucket.getKeyAsString();
                    Aggregations subAggs = bucket.getAggregations();
                    if(subAggs != null){
                        Map<String, Object> itemMap = new HashMap<>();
                        itemMap.put("day", time);
                        for(String key : aggKeyItems){
                            Sum item = subAggs.get(key);
                            Object value = null;
                            if(key.endsWith("Count")){
                                if(item == null){
                                    value = 0.0;
                                }else{
                                    value = (int)item.getValue();
                                }
                            }else {
                                if(item == null){
                                    value = 0.0;
                                }else{
                                    value = BigDecimal.valueOf(item.getValue()).setScale(BigDecimal.ROUND_HALF_UP, 2);
                                }
                            }
                            String itemName = key.substring(3,4).toLowerCase() + key.substring(4,key.length());
                            itemMap.put(itemName, value);
                        }
                        dayArrays.add(itemMap);
                    }
                }
                return WebResult.ok(dayArrays);
            }
        }
        return WebResult.fail("查询失败");
    }



    @GetMapping(value = "/datacenter_dashbord")
    public WebResult dashboard(HttpServletRequest request) throws IOException {
        String agentsStr = request.getParameter("agents");
        List<Integer> agents = new ArrayList<>();
        if(StringUtil.isNotEmpty(agentsStr)){
            String[] agentsArray = agentsStr.split(",");
            for(String agent : agentsArray){
                if(NumberUtils.isPositiveInteger(agent)){
                    agents.add(Integer.valueOf(agent));
                }
            }
        }
        Date now = new Date();
        Date yesterDay = DatesUtil.getBeginDayOfYesterday();
        //昨天到今天时间范围
        DateRange yesterAndNowRange = new DateRange(yesterDay, now);
        //一周前的今天时间范围
        Date oneWeekAge = MyUtil.addTimeSpan(null, -7);
        DateRange weekAgeTodayRange = new DateRange(MyUtil.getStartDay(oneWeekAge), MyUtil.getEndDay(oneWeekAge));
        //全部订单统计 按天统计
        Map dayStatistics = this.getAllCountAndAmount(agents, yesterAndNowRange, weekAgeTodayRange);
        //完成的订单统计  按小时统计
        Map hourStatistics = this.getOrderStatisticsByHour(agents, yesterAndNowRange, weekAgeTodayRange);
        //按月统计订单
        Map monthStatistics = this.statisticsByMonth(agents, new DateRange(DatesUtil.getBeginDayOfLastMonth(), now));

        Map resultMap = new HashMap();
        resultMap.put("byDay", dayStatistics);
        resultMap.put("byHour", hourStatistics);
        resultMap.put("byMonth", monthStatistics);
        return WebResult.ok(resultMap);
    }


    private BoolQueryBuilder initSearchCondition(BoolQueryBuilder builder, List<Integer> agents, DateRange... ranges){
        if(agents.size() > 0){
            builder.must(QueryBuilders.termsQuery("agentId", agents));
        }
        if(ranges != null && ranges.length > 0){
            BoolQueryBuilder timeQueryBuilder = QueryBuilders.boolQuery();
            for(DateRange range : ranges){
                if(range != null && range.getStart() != null && range.getEnd() != null){
                    timeQueryBuilder.should(QueryBuilders.rangeQuery("createTime").from(range.getStart().getTime(), true).to(range.getEnd().getTime(), true));
                }
            }
            if(timeQueryBuilder.hasClauses()){
                builder.must(timeQueryBuilder);
            }
        }
        return builder;
    }

    private boolean isDateRange(Date currDate, DateRange ... ranges){
        if(ranges != null && ranges.length > 0){
            for(DateRange range : ranges){
                if(range == null){
                    continue;
                }
                if(range.isRange(currDate)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 全部订单
     * @param agents
     * @param ranges
     * @return
     * @throws IOException
     */
    private Map<String, Map<String, Object>> getAllCountAndAmount(List<Integer> agents, DateRange... ranges) throws IOException {
        BoolQueryBuilder parentQueryBuilder = QueryBuilders.boolQuery();
        this.initSearchCondition(parentQueryBuilder, agents, ranges);
        //全部订单数量
        ValueCountAggregationBuilder aggAllCount = AggregationBuilders.count("aggAllCount").field("id");
        //全部订单金额
        SumAggregationBuilder aggAllAmount = AggregationBuilders.sum("aggAllAmount").field("totalpay");
        Map notParamMap = new HashMap<>();
        //完成的订单数量
        SumAggregationBuilder aggCompletedCount = AggregationBuilders.sum("aggCompletedCount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_count", notParamMap));
        //完成的订单金额
        SumAggregationBuilder aggCompletedAmount = AggregationBuilders.sum("aggCompletedAmount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_amount", notParamMap));
        //新用户订单数量
        SumAggregationBuilder aggNewuserCount = AggregationBuilders.sum("aggNewuserCount").script(new Script(ScriptType.STORED, null, "runfast_order_of_firsttime_count", notParamMap));
        //新用户订单金额
        SumAggregationBuilder aggNewuserAmount = AggregationBuilders.sum("aggNewuserAmount").script(new Script(ScriptType.STORED, null, "runfast_order_of_firsttime_amount", notParamMap));
        //商家数量
        CardinalityAggregationBuilder cardBusinessCount = AggregationBuilders.cardinality("cardBusinessCount").script(new Script(ScriptType.STORED, null, "runfast_effective_transaction_bus_id", notParamMap));

        //按天分组查询
        DateHistogramAggregationBuilder termsOrderDaily = AggregationBuilders.dateHistogram("termsOrderDaily").field("createTime").dateHistogramInterval(DateHistogramInterval.DAY).timeZone(DateTimeZone.forID("Asia/Shanghai")).format("yyyy-MM-dd 00:00:00");


        termsOrderDaily.subAggregation(aggAllAmount).subAggregation(aggAllCount).subAggregation(aggCompletedCount).subAggregation(aggCompletedAmount).subAggregation(aggNewuserAmount).subAggregation(aggNewuserCount).subAggregation(cardBusinessCount);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.from(0).size(0).aggregation(termsOrderDaily).query(parentQueryBuilder);
        SearchRequest request = new SearchRequest();
        request.source(sourceBuilder).indices(ORDER_INDEX).types(ORDER_TYPE);
        SearchResponse response = restHighLevelClient.search(request);

        Map<String, Map<String, Object>> statisticsMap = new HashMap<>();
        if(response.status() == RestStatus.OK){
            Aggregations aggregations = response.getAggregations();
            if(aggregations != null) {
                Histogram histogramDaily = aggregations.get("termsOrderDaily");
                if (histogramDaily != null && histogramDaily.getBuckets() != null) {
                    for(Histogram.Bucket dailyBucket : histogramDaily.getBuckets()){
                        if(dailyBucket == null){
                            continue;
                        }
                        String key = dailyBucket.getKeyAsString();
                        List<Date> dates = DatesUtil.getDatesInStr(key);
                        if(dates == null || dates.size() == 0){
                            continue;
                        }
                        Date time = dates.get(0);
                        if(!this.isDateRange(time, ranges)){
                            continue;
                        }
                        Aggregations dailyAggs = dailyBucket.getAggregations();
                        if(dailyAggs == null){
                            continue;
                        }

                        ValueCount allCount = dailyAggs.get("aggAllCount");
                        Sum allAmount = dailyAggs.get("aggAllAmount");
                        Sum completedCount = dailyAggs.get("aggCompletedCount");
                        Sum newuserCount = dailyAggs.get("aggNewuserCount");
                        Sum newuserAmount = dailyAggs.get("aggNewuserAmount");
                        Sum completedAmount = dailyAggs.get("aggCompletedAmount");
                        Cardinality businessCount = dailyAggs.get("cardBusinessCount");
                        Long busCount = null;
                        if(businessCount != null ) {
                            busCount = businessCount.getValue();
                        }else{
                            busCount = 0L;
                        }
                        long aCount = allCount == null ? 0 : allCount.getValue();
                        BigDecimal aAmount = allAmount == null ? BigDecimal.ZERO : BigDecimal.valueOf(allAmount.getValue()).setScale(2, BigDecimal.ROUND_HALF_UP);
                        long cCount = completedCount == null ? 0 : (long)completedCount.getValue();
                        long nUCount = newuserCount == null ? 0 : (long)newuserCount.getValue();
                        BigDecimal nUAmount = newuserAmount == null ? BigDecimal.ZERO : BigDecimal.valueOf(newuserAmount.getValue()).setScale(2, BigDecimal.ROUND_HALF_UP);
                        BigDecimal cAmount = completedAmount == null ? BigDecimal.ZERO : BigDecimal.valueOf(completedAmount.getValue()).setScale(2,BigDecimal.ROUND_HALF_UP);
                        String keyName = null;
                        if(DatesUtil.isToday(time)){
                            keyName = "today";
                        }else if(DatesUtil.isYesterday(time)){
                            keyName = "yesterday";
                        }else {
                            keyName = "agoOfSevenDay";
                        }
                        Map dayItem = this.initgetAllCountAndAmountItem(aAmount, aCount, cCount, cAmount, nUCount, nUAmount, busCount);
                        statisticsMap.put(keyName, dayItem);
                    }
                }
            }
        }
        if(!statisticsMap.containsKey("today")){
            Map dayItem = this.initgetAllCountAndAmountItem(BigDecimal.ZERO, 0, 0, BigDecimal.ZERO, 0, BigDecimal.ZERO, 0);
            statisticsMap.put("today", dayItem);
        }
        if(!statisticsMap.containsKey("yesterday")){
            Map dayItem = this.initgetAllCountAndAmountItem(BigDecimal.ZERO, 0, 0, BigDecimal.ZERO, 0, BigDecimal.ZERO, 0);
            statisticsMap.put("yesterday", dayItem);
        }
        if(!statisticsMap.containsKey("agoOfSevenDay")){
            Map dayItem = this.initgetAllCountAndAmountItem(BigDecimal.ZERO, 0, 0, BigDecimal.ZERO, 0, BigDecimal.ZERO, 0);
            statisticsMap.put("agoOfSevenDay", dayItem);
        }
        return statisticsMap;
    }

    private Map initgetAllCountAndAmountItem(BigDecimal aAmount, long aCount, long cCount, BigDecimal cAmount, long nUCount, BigDecimal nUAmount, long busCount){
        Map<String, Object> dayItem = new HashMap<>();
        dayItem.put("allAmount", aAmount);
        dayItem.put("allCount", aCount);
        dayItem.put("completedCount", cCount);
        dayItem.put("completedAmount", cAmount);
        dayItem.put("newuserCount", nUCount);
        dayItem.put("newuserAmount", nUAmount);
        dayItem.put("busCount", busCount);
        return dayItem;
    }


    private Map getOrderStatisticsByHour(List<Integer> agents, DateRange... ranges) throws IOException {
        BoolQueryBuilder parentQueryBuilder = QueryBuilders.boolQuery();
        this.initSearchCondition(parentQueryBuilder, agents, ranges);
        parentQueryBuilder.must(QueryBuilders.termQuery("status", 8));
        //按小时分组查询
        DateHistogramAggregationBuilder termsOrderDaily = AggregationBuilders.dateHistogram("termsOrderHour").field("createTime").dateHistogramInterval(DateHistogramInterval.HOUR).timeZone(DateTimeZone.forID("Asia/Shanghai")).format("yyyy-MM-dd HH:00:00");
        //完成支付金额
        SumAggregationBuilder aggCompletedAmount = AggregationBuilders.sum("aggCompletedAmount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_amount", new HashMap<>()));
        termsOrderDaily.subAggregation(aggCompletedAmount);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(parentQueryBuilder).size(0).from(0).aggregation(termsOrderDaily);
        SearchRequest request = new SearchRequest();
        request.source(sourceBuilder).indices(ORDER_INDEX).types(ORDER_TYPE);
        SearchResponse response = restHighLevelClient.search(request);
        List<Object> today = new ArrayList<>();
        List<Object> yesterday = new ArrayList<>();
        List<Object> ageOfSevenDays = new ArrayList<>();
        if(response.status() == RestStatus.OK){
            Aggregations aggregations = response.getAggregations();
            if(aggregations != null){
                Histogram histogramHour = aggregations.get("termsOrderHour");
                if(histogramHour != null){
                    List<? extends Histogram.Bucket> buckets = histogramHour.getBuckets();
                    if(buckets != null){
                        for (Histogram.Bucket bucket : buckets){
                            if(bucket == null){
                                continue;
                            }
                            String timeStr = bucket.getKeyAsString();
                            List<Date> dates = DatesUtil.getDatesInStr(timeStr);
                            if(dates == null || dates.size() == 0){
                                continue;
                            }
                            Date time = dates.get(0);
                            if(!this.isDateRange(time, ranges)){
                                continue;
                            }
                            Aggregations itemAggregatins = bucket.getAggregations();
                            if(itemAggregatins == null){
                                continue;
                            }
                            Sum completedAmountSum = itemAggregatins.get("aggCompletedAmount");
                            Double completedAmount = null;
                            if(completedAmountSum == null){
                                completedAmount = 0.0;
                            }else{
                                completedAmount = BigDecimal.valueOf(completedAmountSum.getValue()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            }
                            Map item = new HashMap();
                            item.put("hour", MyUtil.getHourOfDay(time));
                            item.put("amount", completedAmount);
                            if(DatesUtil.isToday(time)){
                                today.add(item);
                            }else if(DatesUtil.isYesterday(time)){
                                yesterday.add(item);
                            }else {
                                ageOfSevenDays.add(item);
                            }
                        }
                    }
                }
            }
        }
        Map resultMap = new HashMap();
        resultMap.put("today", today);
        resultMap.put("yesterday", yesterday);
        resultMap.put("ageOfSevenDay", ageOfSevenDays);
        return resultMap;
    }

    private Map statisticsByMonth(List<Integer> agents, DateRange... ranges) throws IOException {
        BoolQueryBuilder parentQueryBuilder = QueryBuilders.boolQuery();
        this.initSearchCondition(parentQueryBuilder, agents, ranges);
        //按月分组查询
        DateHistogramAggregationBuilder termsOrderDaily = AggregationBuilders.dateHistogram("termsOrderByMonth").field("createTime").dateHistogramInterval(DateHistogramInterval.MONTH).timeZone(DateTimeZone.forID("Asia/Shanghai")).format("yyyy-MM-dd 00:00:00");
        Map notParamMap = new HashMap<>();
        //全部订单数量
        ValueCountAggregationBuilder aggAllCount = AggregationBuilders.count("aggAllCount").field("id");
        //全部订单金额
        SumAggregationBuilder aggAllAmount = AggregationBuilders.sum("aggAllAmount").field("totalpay");
        //超时完成订单数量
        SumAggregationBuilder aggOuttimeCount = AggregationBuilders.sum("aggOuttimeCount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_outtime_count", notParamMap));
        //差评订单数量
        SumAggregationBuilder aggNegativeCount = AggregationBuilders.sum("aggNegativeCount").script(new Script(ScriptType.STORED, null, "runfast_order_negative_count", notParamMap));
        //取消订单数量
        SumAggregationBuilder aggCancelCount = AggregationBuilders.sum("aggCancelCount").script(new Script(ScriptType.STORED, null, "runfast_order_canceled_count", notParamMap));
        termsOrderDaily.subAggregation(aggAllCount).subAggregation(aggAllAmount).subAggregation(aggOuttimeCount).subAggregation(aggNegativeCount).subAggregation(aggCancelCount);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.from(0).size(0).query(parentQueryBuilder).aggregation(termsOrderDaily);
        SearchRequest request = new SearchRequest();
        request.source(sourceBuilder).indices(ORDER_INDEX).types(ORDER_TYPE);
        SearchResponse response = restHighLevelClient.search(request);
        Map resultMap = new HashMap();
        if(response.status() == RestStatus.OK){
            Aggregations aggregations = response.getAggregations();
            if(aggregations != null) {
                Histogram orderByMonth = aggregations.get("termsOrderByMonth");
                if(orderByMonth != null){
                    List<? extends Histogram.Bucket> buckets = orderByMonth.getBuckets();
                    if(buckets != null){
                        for(Histogram.Bucket bucket : buckets){
                            if(bucket == null){
                                continue;
                            }
                            String key = bucket.getKeyAsString();
                            List<Date> dates = DatesUtil.getDatesInStr(key);
                            if(dates == null || dates.size() == 0){
                                continue;
                            }
                            Date time = dates.get(0);
                            Aggregations itemAggregations = bucket.getAggregations();
                            if(itemAggregations == null){
                                continue;
                            }
                            ValueCount allCountValue = itemAggregations.get("aggAllCount");
                            Sum allAmountValue = itemAggregations.get("aggAllAmount");
                            Sum outtimeCountValue = itemAggregations.get("aggOuttimeCount");
                            Sum negativeCountValue = itemAggregations.get("aggNegativeCount");
                            Sum cancelCountValue = itemAggregations.get("aggCancelCount");

                            Long allCount = null;
                            BigDecimal allAmount = null;
                            Long outtimeCount = null;
                            Long negativeCount = null;
                            Long cancelCount = null;
                            if(allCountValue == null){
                                allCount = 0L;
                            }else {
                                allCount = allCountValue.getValue();
                            }
                            if(allAmountValue == null){
                                allAmount = BigDecimal.ZERO;
                            }else{
                                allAmount = BigDecimal.valueOf(allAmountValue.getValue()).setScale(2,BigDecimal.ROUND_HALF_UP);
                            }
                            if(outtimeCountValue == null){
                                outtimeCount = 0L;
                            }else{
                                outtimeCount = (long)outtimeCountValue.getValue();
                            }
                            if(negativeCountValue == null){
                                negativeCount = 0L;
                            }else{
                                negativeCount = (long)negativeCountValue.getValue();
                            }
                            if(cancelCountValue == null){
                                cancelCount = 0L;
                            }else{
                                cancelCount = (long)cancelCountValue.getValue();
                            }
                            Map item = this.initStatisticsByMonthItem(allCount, allAmount, outtimeCount, negativeCount, cancelCount);
                            if(DatesUtil.isThismonth(time)){
                                resultMap.put("thisMonth", item);
                            }else if(DatesUtil.isLastmonth(time)){
                                resultMap.put("lastMonth", item);
                            }
                        }
                    }
                }
            }
        }
        if(!resultMap.containsKey("thisMonth")){
            Map item = this.initStatisticsByMonthItem(0L, BigDecimal.ZERO, 0L, 0L, 0L);
            resultMap.put("thisMonth", item);
        }
        if(!resultMap.containsKey("lastMonth")){
            Map item = this.initStatisticsByMonthItem(0L, BigDecimal.ZERO, 0L, 0L, 0L);
            resultMap.put("lastMonth", item);
        }
        return resultMap;
    }

    private Map initStatisticsByMonthItem(Long allCount, BigDecimal allAmount, Long outtimeCount, Long negativeCount, Long cancelCount){
        Map item = new HashMap();
        item.put("allCount", allCount);
        item.put("allAmount", allAmount);
        item.put("outtimeCount", outtimeCount);
        item.put("negativeCount", negativeCount);
        item.put("cancelCount", cancelCount);
        return item;
    }
}
